#!/usr/bin/env python
# encoding: utf-8


"""
@file: daishushifanwei.py
@time: 2016/11/21 上午9:55
"""
from functools import reduce

from mathsolver.functions.base import *
from mathsolver.functions.budengshi import common_opers as co
from sympy import S, solveset
import re
from mathsolver.functions.budengshi.ineqs_funcs import AlgebraScope
from mathsolver.functions.budengshi.params_ineqs_funcs import CoeffIneq


# 代数式的范围问题

# 已知-2<x<y<3,则x-y的取值范围为()         求代数式范围  BUG
# 已知1<a+b<3,-1<a-b<1,则2a+b的取值范围是. 待定系数法
class DaiShuShiFanWei001(BaseFunction):
    @staticmethod
    def ineqs_symbs(ineqs):
        ineqs_fac = filter(lambda a: str(a) not in ['<=', '<', '>=', '>'], co.flatten(ineqs))
        ineqs_fac = map(sympify, ineqs_fac)
        ineqs_fac_str = reduce(lambda a, b: a + b, ineqs_fac)
        e = sympify(ineqs_fac_str)
        return list(map(str, e.free_symbols))

    @staticmethod
    def right_dig(dig_str):
        dig_p = r'\((-?\d+?)\)'
        digs = re.findall(dig_p, dig_str)
        tmp_str = dig_str
        if digs:
            for d in digs:
                tmp_str = tmp_str.replace('(%s)' % str(d), d)
        return tmp_str

    def solver(self, *args):
        ineqs = args[0].value
        algebra_flag = True
        ineq_expr_list = args[0].value
        for i in ineq_expr_list:
            if isinstance(i, list):
                algebra_flag = False
                break
            if str(i) not in ['<=', '<', '>=', '>']:
                si = sympify(i)
                if not si.is_real and len(si.free_symbols) > 1:
                    algebra_flag = False
                    break
        if algebra_flag:
            arg0 = ''.join(args[0].value)
            arg0 = DaiShuShiFanWei001.right_dig(arg0)
            arg1 = args[1]
            return AlgebraScope(verbose=True).solver(arg0, arg1)
        elif len(ineqs) == 2:
            symbs = DaiShuShiFanWei001.ineqs_symbs(ineqs)
            if len(symbs) == 3:
                ineq1 = ''.join(ineqs[0])
                ineq1 = DaiShuShiFanWei001.right_dig(ineq1)
                ineq2 = ''.join(ineqs[1])
                ineq2 = DaiShuShiFanWei001.right_dig(ineq2)
                target_poly = args[-1]
                return AlgebraScope(verbose=True).solver(ineq1, ineq2, target_poly)
        # 已知1<a+b<3,-1<a-b<1,则2a+b的取值范围是. 待定系数法
        ineq1 = ''.join(ineqs[0])
        ineq1 = DaiShuShiFanWei001.right_dig(ineq1)
        ineq2 = ''.join(ineqs[1])
        ineq2 = DaiShuShiFanWei001.right_dig(ineq2)
        poly = args[-1]
        self.label.add('求代数式的范围')
        return CoeffIneq(verbose=True).solver([ineq1, ineq2], poly)


# 设a>2,则a+\\frac{1}{a-2}的最小值是()
class DaiShuShiFanWei002(BaseFunction):
    def solver(self, *args):
        self.label.add('均值不等式')
        if not (isinstance(args[0], BaseIneq) and isinstance(args[1], BasePoly)):
            raise Exception('Type Match Error')
        ineq = args[0]
        l, o, r = ineq.sympify()
        ineq_f = l - r
        symbs1 = list(ineq_f.free_symbols)
        f = args[1].sympify()
        symbs2 = list(f.free_symbols)
        if not (len(symbs1) == 1 and len(symbs2) == 1):
            raise Exception("Type Match Error")
        if str(symbs1[0]) != str(symbs2[0]):
            raise Exception("Type Match Error")
        symb = symbs1[0]
        text = args[3]
        ineq_solve = solveset(str(ineq_f) + o + '0', domain=S.Reals)
        if ineq_solve.left.is_real:
            v = ineq_solve.left
            o2 = '>'
        self.steps.append(['\because ' + co.print_interval(ineq_solve), '\therefore '])
        return self


# 所有求代数式范围的元函数
# input: paramer1:ineqs或者ineq; paramer2:目标poly
# output: 目标区间
class DaiShuShiFanWei(BaseFunction):
    CLS = [DaiShuShiFanWei001, DaiShuShiFanWei002, AlgebraScope, CoeffIneq]

    def solver(self, *args):
        r = None
        for cl in DaiShuShiFanWei.CLS:
            try:
                r = cl(verbose=True).solver(*args)
                break
            except Exception:
                pass
        if not r:
            raise 'try fail'
        return r


if __name__ == '__main__':
    r = DaiShuShiFanWei(verbose=True).solver(BaseIneqs([['-2', '<', 'x', '<', 'y', '<', '3'], ]), BasePoly('x-y'))
